﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using repliback4.Net.Identification;
using repliback4.Net.Protocol.Messages.Attributes;
using repliback4.Xml;
using repliback4.Xml.Extensions;


namespace repliback4.Net.Protocol.Messages {

    public abstract class Tag {

        public TagRegistry Registry;
        protected XmlDocument xdoc;
        protected XmlElement xml;
        public XmlElement Xml {
            get {
                if ( this.xml == null ) {

                    RequestTag[] _attrs = ( RequestTag[] ) this.GetType( ).GetCustomAttributes( typeof( RequestTag ), false );
                    if ( _attrs.Length == 1 ) {
                        RequestTag _attr = _attrs[0];
                        this.xml = xdoc.CreateElement( _attr.Prefix, _attr.Name, _attr.Namespace );
                    } else {
                        throw new Exception( "something is wrong!" );
                    }
                };
                return this.xml;

            }
        }
        protected Tag ( XmlDocument xDoc ) {
            if ( xDoc == null ) {
                throw new ArgumentNullException( "xDoc", String.Format( "xDoc must not be null for {0}", this.GetType( ).FullName ) );
            }
            this.xdoc = xDoc;
        }
        public static implicit operator XmlElement ( Tag tag ) {
            return tag.Xml;
        }

        public String DefaultNamespaceURI {
            set {
                String ns = this.Xml.OwnerDocument.GetNamespaceOfPrefix( "xmlns" );
                this.Xml.SetAttribute( "xmlns", value );
            }

        }
        public String TagName {
            get { return this.Xml.XmlQualifiedName( ).ToString( ); }
        }
    }

    public abstract class ReplibackTag : Tag {

        //public static void Initialize ( StanzaSettings settings ) {
        //}

        public ReplibackTag ( XmlElement element )
            : base( element.OwnerDocument ) {
            this.xml = ( XmlElement ) element.Clone( );
        }
        public ReplibackTag ( XmlDocument xDoc ) : base( xDoc ) { }
        public Rid To {
            get {
                //try {
                return Rid.Parse( this.Xml.GetAttribute( "to" ) );
                //} catch ( Exception e ) {
                //    return new Rid( "", "", "" );
                //}
            }
            set {
                this.Xml.SetAttribute( "to", value.ToString( Rid.RidForm.Full ) );
            }
        }

        public Rid From {
            get {
                //try {
                return Rid.Parse( this.Xml.GetAttribute( "from" ) );
                //} catch ( Exception e ) {
                //    return new Rid( "", "", "" );
                //}
            }
            set {
                this.Xml.SetAttribute( "from", value.ToString( Rid.RidForm.Full ) );
            }
        }


    }

    public abstract class BaseStream : ReplibackTag {
        public BaseStream ( XmlElement element ) : base( element ) { }
        public BaseStream ( XmlDocument xDoc ) : base( xDoc ) { }
    }
    public abstract class Stanza : ReplibackTag {
        public Stanza ( XmlDocument xDoc ) : base( xDoc ) { }
        public Stanza ( XmlElement element ) : base( element ) { }
    }

}
